/*******************************************************************************
 * Copyright 2012 Fatminds, Inc
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/
package com.fatminds.vaadin_cmis_integration.demo;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.apache.chemistry.opencmis.client.api.Document;
import org.apache.chemistry.opencmis.client.api.Folder;
import org.apache.chemistry.opencmis.client.api.Policy;
import org.apache.chemistry.opencmis.client.api.Session;
import org.apache.chemistry.opencmis.commons.PropertyIds;
import org.apache.chemistry.opencmis.commons.data.Ace;
import org.apache.chemistry.opencmis.commons.data.ContentStream;
import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.ContentStreamImpl;
import org.apache.commons.io.IOUtils;
import org.dellroad.stuff.vaadin.ContextApplication;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;

import com.fatminds.cmis.form.CmisForm;
import com.fatminds.vaadin.cmis.CmisContainer;
import com.fatminds.vaadin.cmis.CmisItem;
import com.fatminds.vaadin.cmis.components.CmisList;
import com.fatminds.vaadin.cmis.name.PropertyCmisNameGenerator;
import com.vaadin.annotations.AutoGenerated;
import com.vaadin.event.ItemClickEvent;
import com.vaadin.event.ItemClickEvent.ItemClickListener;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.Component;
import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.GridLayout;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.RichTextArea;
import com.vaadin.ui.Upload;
import com.vaadin.ui.VerticalLayout;

@Configurable(preConstruction=true)
public class DemoPage extends CustomComponent {

	@AutoGenerated
	private VerticalLayout mainLayout;
	@AutoGenerated
	private GridLayout gridLayout_1;
	@AutoGenerated
	private VerticalLayout verticalLayout_4;
	@AutoGenerated
	private DemoTemplateForm demoTemplateForm_1;
	@AutoGenerated
	private VerticalLayout verticalLayout_3;
	@AutoGenerated
	private Button btnSaveContent;
	@AutoGenerated
	private RichTextArea richTextArea_1;
	@AutoGenerated
	private HorizontalLayout horizontalLayout_3;
	@AutoGenerated
	private Button btnRefresh;
	@AutoGenerated
	private CmisList cmisList_1;
	@AutoGenerated
	private GridLayout gridLayout_2;
	@AutoGenerated
	private VerticalLayout verticalLayout_2;
	@AutoGenerated
	private Upload upload_1;
	@AutoGenerated
	private Label label_1;

	/*- VaadinEditorProperties={"grid":"RegularGrid,20","showGrid":true,"snapToGrid":true,"snapToObject":true,"movingGuides":false,"snappingDistance":10} */

	

	/*- VaadinEditorProperties={"grid":"RegularGrid,20","showGrid":true,"snapToGrid":true,"snapToObject":true,"movingGuides":false,"snappingDistance":10} */

	

	/*- VaadinEditorProperties={"grid":"RegularGrid,20","showGrid":true,"snapToGrid":true,"snapToObject":true,"movingGuides":false,"snappingDistance":10} */

	

	/*- VaadinEditorProperties={"grid":"RegularGrid,20","showGrid":true,"snapToGrid":true,"snapToObject":true,"movingGuides":false,"snappingDistance":10} */

	

	/*- VaadinEditorProperties={"grid":"RegularGrid,20","showGrid":true,"snapToGrid":true,"snapToObject":true,"movingGuides":false,"snappingDistance":10} */

	

	/*- VaadinEditorProperties={"grid":"RegularGrid,20","showGrid":true,"snapToGrid":true,"snapToObject":true,"movingGuides":false,"snappingDistance":10} */

	

	/*- VaadinEditorProperties={"grid":"RegularGrid,20","showGrid":true,"snapToGrid":true,"snapToObject":true,"movingGuides":false,"snappingDistance":10} */

	

	/*- VaadinEditorProperties={"grid":"RegularGrid,20","showGrid":true,"snapToGrid":true,"snapToObject":true,"movingGuides":false,"snappingDistance":10} */

	

	/*- VaadinEditorProperties={"grid":"RegularGrid,20","showGrid":true,"snapToGrid":true,"snapToObject":true,"movingGuides":false,"snappingDistance":10} */

	

	/*- VaadinEditorProperties={"grid":"RegularGrid,20","showGrid":true,"snapToGrid":true,"snapToObject":true,"movingGuides":false,"snappingDistance":10} */

	

	/*- VaadinEditorProperties={"grid":"RegularGrid,20","showGrid":true,"snapToGrid":true,"snapToObject":true,"movingGuides":false,"snappingDistance":10} */

	

	/*- VaadinEditorProperties={"grid":"RegularGrid,20","showGrid":true,"snapToGrid":true,"snapToObject":true,"movingGuides":false,"snappingDistance":10} */

	

	/*- VaadinEditorProperties={"grid":"RegularGrid,20","showGrid":true,"snapToGrid":true,"snapToObject":true,"movingGuides":false,"snappingDistance":10} */

	

	/*- VaadinEditorProperties={"grid":"RegularGrid,20","showGrid":true,"snapToGrid":true,"snapToObject":true,"movingGuides":false,"snappingDistance":10} */

	

	/*- VaadinEditorProperties={"grid":"RegularGrid,20","showGrid":true,"snapToGrid":true,"snapToObject":true,"movingGuides":false,"snappingDistance":10} */

	

	/*- VaadinEditorProperties={"grid":"RegularGrid,20","showGrid":true,"snapToGrid":true,"snapToObject":true,"movingGuides":false,"snappingDistance":10} */

	

	/*- VaadinEditorProperties={"grid":"RegularGrid,20","showGrid":true,"snapToGrid":true,"snapToObject":true,"movingGuides":false,"snappingDistance":10} */

	

	/*- VaadinEditorProperties={"grid":"RegularGrid,20","showGrid":true,"snapToGrid":true,"snapToObject":true,"movingGuides":false,"snappingDistance":10} */

	

	/*- VaadinEditorProperties={"grid":"RegularGrid,20","showGrid":true,"snapToGrid":true,"snapToObject":true,"movingGuides":false,"snappingDistance":10} */

	

	/*- VaadinEditorProperties={"grid":"RegularGrid,20","showGrid":true,"snapToGrid":true,"snapToObject":true,"movingGuides":false,"snappingDistance":10} */

	

	/*- VaadinEditorProperties={"grid":"RegularGrid,20","showGrid":true,"snapToGrid":true,"snapToObject":true,"movingGuides":false,"snappingDistance":10} */

	

	/*- VaadinEditorProperties={"grid":"RegularGrid,20","showGrid":true,"snapToGrid":true,"snapToObject":true,"movingGuides":false,"snappingDistance":10} */

	

	/*- VaadinEditorProperties={"grid":"RegularGrid,20","showGrid":true,"snapToGrid":true,"snapToObject":true,"movingGuides":false,"snappingDistance":10} */

	

	/*- VaadinEditorProperties={"grid":"RegularGrid,20","showGrid":true,"snapToGrid":true,"snapToObject":true,"movingGuides":false,"snappingDistance":10} */

	

	/*- VaadinEditorProperties={"grid":"RegularGrid,20","showGrid":true,"snapToGrid":true,"snapToObject":true,"movingGuides":false,"snappingDistance":10} */

	

	/*- VaadinEditorProperties={"grid":"RegularGrid,20","showGrid":true,"snapToGrid":true,"snapToObject":true,"movingGuides":false,"snappingDistance":10} */

	private static final Logger log = LoggerFactory.getLogger(DemoPage.class);
	
    @Autowired
    protected Session cmisSession;

	
	public static final String DEMO_SUBFOLDER = "cmis-demo";

	/**
	 * Code-drawn components
	 */
	protected CmisForm cmisForm;

	public DemoPage() {
		buildMainLayout();
		setCompositionRoot(mainLayout);
	}
	
	/**
	 * To be called by creator
	 */
	public void init() {
        final CmisContainer<Document> docs = getUploadContainer();

        setupUploadReceiver(docs);	
        setupUploadTable(docs);
        setupContentSaveButton();
		
        btnRefresh.addListener(new ClickListener(){

			public void buttonClick(ClickEvent event) {
				((CmisContainer)cmisList_1.getContainerDataSource()).refresh();
			}
        	
        });
		

	}
	
	protected void setupContentSaveButton(){
		btnSaveContent.addListener(new ClickListener() {
			
			public void buttonClick(ClickEvent event) {
				Button b = event.getButton();
				b.setEnabled(false);
				// Ensure that a document is currently selected
				String selectedItemId = (String)cmisList_1.getValue();
				if (null == selectedItemId)
					return;
				CmisItem item = (CmisItem) cmisList_1.getContainerDataSource().getItem(selectedItemId);
				Document doc = (Document) item.getCmisObject();
				putContentToDocument(doc);
				b.setEnabled(true);
			}
		});
	}
	
	protected void setupUploadReceiver(CmisContainer<?> docs){
		// Set up upload handler
		// Note, ur refreshes the container (and thereby the list) when an upload succeeds
        final UploadReceiver ur = new UploadReceiver("D:cmiscustom:document", docs.getRootFolder(), docs, ContextApplication.get());
        upload_1.setReceiver(ur);
		upload_1.addListener((Upload.SucceededListener)ur);
		upload_1.addListener((Upload.FailedListener)ur);
	}
	
	protected void setupUploadTable(CmisContainer<?> docs){
        // Set up table
		final DemoPage thisPage = this;
		cmisList_1.setContainerDataSource(docs);
		cmisList_1.setVisibleColumns(new String[]{"cmis:name", "cmiscustom:docprop_string"});
		cmisList_1.setColumnHeaders(new String[]{"Filename", "Filename in Custom property"});
		cmisList_1.addDeleteButtonColumn();
		
		// Add handler for getting/consuming data from RTA
		cmisList_1.addListener(new ItemClickListener() {
			
			public void itemClick(ItemClickEvent event) {
				CmisItem item = (CmisItem)event.getItem();
				thisPage.putContentToRta(item);
				DemoFieldFactory fieldFactory = new DemoFieldFactory();
				final DemoTemplateForm formTemplate = new DemoTemplateForm();
				cmisForm = new CmisForm(formTemplate, fieldFactory, new PropertyCmisNameGenerator(new String[] {"cmiscustom:docprop_string"}));
				cmisForm.setHeight("250px");
				cmisForm.setWidth("350px");
				Component oldForm = verticalLayout_4.getComponent(0);
				verticalLayout_4.replaceComponent(oldForm, cmisForm);
				cmisForm.setItemDataSource(item);
			}
		});
		
	}
	
	protected void putContentToDocument(Document doc){
		List<Ace> addAces = new LinkedList<Ace>();
		List<Ace> removeAces = new LinkedList<Ace>();
		List<Policy> policies = new LinkedList<Policy>();

		try {
			ContentStream cs = doc.getContentStream();
			String content = (String)richTextArea_1.getValue();
			ContentStream contentStream = 
					new ContentStreamImpl(
							cs.getFileName(), 
							null, 
							cs.getMimeType(),
							new ByteArrayInputStream(content.getBytes()));
			doc.setContentStream(contentStream, true, true);
			doc.refresh(); // Veddddy important, yea verily
		}
		catch(Exception e){
			e.printStackTrace();
			return;
		}

	}
	
	protected void putContentToRta(CmisItem item){
		Document doc = (Document)item.getCmisObject();
		ContentStream cs = doc.getContentStream();
		String text;
		if (null != cs){
			try {
				text = IOUtils.toString(cs.getStream(), "UTF-8");
			} catch (IOException e) {
				e.printStackTrace();
				return;
			}
			richTextArea_1.setValue(text);
		}
	}

	
    protected CmisContainer<Document> getUploadContainer() {
        // Upload list
        CmisContainer<Document> docs = new CmisContainer<Document>(
        		// Include aspects ONLY if not specified as <mandatory-aspects> in Alfresco model (these are picked up automagically)
        		"D:cmiscustom:document", 
        		// All objects managed by this CmisContainer will have this folder as parent
        		getDemoFolder(), 
        		Document.class,
        		// Pagination off (lazy-loading on)
        		0,
        		// Specify ordering of container contents using CMISSQL
        		"cmis:name ASC");
        docs.initContainerProperties();
        docs.populate();
        return docs;
    }
    
    protected Folder getDemoFolder() {
        Folder rootFolder = (Folder)cmisSession.getRootFolder();
        if (null == rootFolder) {
        	throw new IllegalStateException("Cannot retrieve root folder");
        }
        log.info("Got handle to root CMIS repository folder");
        
        Folder demoFolder;
        try {
        	demoFolder = (Folder) cmisSession.getObjectByPath("/" + DEMO_SUBFOLDER);
        }
        catch (CmisObjectNotFoundException e) {
        	log.info("Creating demo folder " + DEMO_SUBFOLDER);
        	Map<String, String> props = new HashMap<String, String>();
        	props.put(PropertyIds.OBJECT_TYPE_ID, "F:cmiscustom:folder");
        	props.put(PropertyIds.NAME, DEMO_SUBFOLDER);
        	demoFolder = rootFolder.createFolder(props);        	
        }
        return demoFolder;
    }

	
	@AutoGenerated
	private VerticalLayout buildMainLayout() {
		// common part: create layout
		mainLayout = new VerticalLayout();
		mainLayout.setImmediate(false);
		mainLayout.setWidth("900px");
		mainLayout.setHeight("800px");
		mainLayout.setMargin(true);
		mainLayout.setSpacing(true);
		
		// top-level component properties
		setWidth("900px");
		setHeight("800px");
		
		// gridLayout_2
		gridLayout_2 = buildGridLayout_2();
		mainLayout.addComponent(gridLayout_2);
		mainLayout.setComponentAlignment(gridLayout_2, new Alignment(20));
		
		// horizontalLayout_3
		horizontalLayout_3 = buildHorizontalLayout_3();
		mainLayout.addComponent(horizontalLayout_3);
		mainLayout.setComponentAlignment(horizontalLayout_3, new Alignment(20));
		
		// gridLayout_1
		gridLayout_1 = buildGridLayout_1();
		mainLayout.addComponent(gridLayout_1);
		mainLayout.setExpandRatio(gridLayout_1, 1.0f);
		mainLayout.setComponentAlignment(gridLayout_1, new Alignment(20));
		
		return mainLayout;
	}

	@AutoGenerated
	private GridLayout buildGridLayout_2() {
		// common part: create layout
		gridLayout_2 = new GridLayout();
		gridLayout_2.setImmediate(false);
		gridLayout_2.setWidth("90.0%");
		gridLayout_2.setHeight("50px");
		gridLayout_2.setMargin(false);
		gridLayout_2.setColumns(2);
		
		// verticalLayout_2
		verticalLayout_2 = buildVerticalLayout_2();
		gridLayout_2.addComponent(verticalLayout_2, 0, 0);
		gridLayout_2.setComponentAlignment(verticalLayout_2, new Alignment(24));
		
		return gridLayout_2;
	}

	@AutoGenerated
	private VerticalLayout buildVerticalLayout_2() {
		// common part: create layout
		verticalLayout_2 = new VerticalLayout();
		verticalLayout_2.setImmediate(false);
		verticalLayout_2.setWidth("-1px");
		verticalLayout_2.setHeight("-1px");
		verticalLayout_2.setMargin(false);
		
		// label_1
		label_1 = new Label();
		label_1.setImmediate(false);
		label_1.setWidth("-1px");
		label_1.setHeight("-1px");
		label_1.setValue("Upload a text or html file");
		verticalLayout_2.addComponent(label_1);
		verticalLayout_2.setComponentAlignment(label_1, new Alignment(33));
		
		// upload_1
		upload_1 = new Upload();
		upload_1.setImmediate(false);
		upload_1.setWidth("100.0%");
		upload_1.setHeight("100.0%");
		verticalLayout_2.addComponent(upload_1);
		verticalLayout_2.setComponentAlignment(upload_1, new Alignment(33));
		
		return verticalLayout_2;
	}

	@AutoGenerated
	private HorizontalLayout buildHorizontalLayout_3() {
		// common part: create layout
		horizontalLayout_3 = new HorizontalLayout();
		horizontalLayout_3.setImmediate(false);
		horizontalLayout_3.setWidth("100.0%");
		horizontalLayout_3.setHeight("250px");
		horizontalLayout_3.setMargin(false);
		
		// cmisList_1
		cmisList_1 = new CmisList();
		cmisList_1.setImmediate(false);
		cmisList_1.setWidth("700px");
		cmisList_1.setHeight("250px");
		horizontalLayout_3.addComponent(cmisList_1);
		
		// btnRefresh
		btnRefresh = new Button();
		btnRefresh.setCaption("Refresh container");
		btnRefresh.setImmediate(true);
		btnRefresh.setWidth("150px");
		btnRefresh.setHeight("-1px");
		horizontalLayout_3.addComponent(btnRefresh);
		horizontalLayout_3.setComponentAlignment(btnRefresh, new Alignment(6));
		
		return horizontalLayout_3;
	}

	@AutoGenerated
	private GridLayout buildGridLayout_1() {
		// common part: create layout
		gridLayout_1 = new GridLayout();
		gridLayout_1.setImmediate(false);
		gridLayout_1.setWidth("100.0%");
		gridLayout_1.setHeight("500px");
		gridLayout_1.setMargin(false);
		gridLayout_1.setSpacing(true);
		gridLayout_1.setColumns(2);
		gridLayout_1.setRows(3);
		
		// verticalLayout_3
		verticalLayout_3 = buildVerticalLayout_3();
		gridLayout_1.addComponent(verticalLayout_3, 0, 0);
		
		// verticalLayout_4
		verticalLayout_4 = buildVerticalLayout_4();
		gridLayout_1.addComponent(verticalLayout_4, 1, 0);
		gridLayout_1.setComponentAlignment(verticalLayout_4, new Alignment(6));
		
		return gridLayout_1;
	}

	@AutoGenerated
	private VerticalLayout buildVerticalLayout_3() {
		// common part: create layout
		verticalLayout_3 = new VerticalLayout();
		verticalLayout_3.setImmediate(false);
		verticalLayout_3.setWidth("-1px");
		verticalLayout_3.setHeight("-1px");
		verticalLayout_3.setMargin(false);
		verticalLayout_3.setSpacing(true);
		
		// richTextArea_1
		richTextArea_1 = new RichTextArea();
		richTextArea_1.setImmediate(false);
		richTextArea_1.setWidth("450px");
		richTextArea_1.setHeight("250px");
		verticalLayout_3.addComponent(richTextArea_1);
		
		// btnSaveContent
		btnSaveContent = new Button();
		btnSaveContent.setCaption("Save rich editor changes to cm:content");
		btnSaveContent.setImmediate(true);
		btnSaveContent.setWidth("450px");
		btnSaveContent.setHeight("-1px");
		verticalLayout_3.addComponent(btnSaveContent);
		
		return verticalLayout_3;
	}

	@AutoGenerated
	private VerticalLayout buildVerticalLayout_4() {
		// common part: create layout
		verticalLayout_4 = new VerticalLayout();
		verticalLayout_4.setImmediate(false);
		verticalLayout_4.setWidth("-1px");
		verticalLayout_4.setHeight("-1px");
		verticalLayout_4.setMargin(false);
		
		// demoTemplateForm_1
		demoTemplateForm_1 = new DemoTemplateForm();
		demoTemplateForm_1.setImmediate(false);
		demoTemplateForm_1.setWidth("350px");
		demoTemplateForm_1.setHeight("250px");
		verticalLayout_4.addComponent(demoTemplateForm_1);
		
		return verticalLayout_4;
	}

}
